﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using Looptribe.Moodlin8.Model;
using Looptribe.Moodlin8.Model.Api;
using Looptribe.Moodlin8.View;
using Looptribe.WinRT.Toolkit;
using Windows.Foundation;
using Windows.UI.Xaml;


namespace Looptribe.Moodlin8.ViewModel
{
    public class CourseViewModel : LoadingViewModel
    {
        private readonly CourseModulesGroup _courseModulesGroup = new CourseModulesGroup();
        //private readonly CourseUsersGroup _courseUsersGroup = new CourseUsersGroup();

        private readonly ObservableCollection<CourseUserWrapper> _teachers = new ObservableCollection<CourseUserWrapper>();
        public ObservableCollection<CourseUserWrapper> Teachers { get { return _teachers; } }

        public ICommand GotoCourseContentCommand { get; private set; }
        public ICommand GotoUsersCommand { get; private set; }
        public ICommand GotoEventsCommand { get; private set; }
        public ICommand GotoTeacherCommand { get; private set; }

        public ICommand GotoNextAssignmentsCommand { get; private set; }
        public ICommand GotoCorrectedAssignmentsCommand { get; private set; }

        public ICommand ModuleContentCommand { get; private set; }

        public ICommand PinToStartCommand { get; private set; }

        private readonly ObservableCollection<CourseContentWrapper> _units = new ObservableCollection<CourseContentWrapper>();
        public ObservableCollection<CourseContentWrapper> Units
        {
            get { return _units; }
        }

        private Course _course;
        public Course Course
        {
            set { Set(() => Course, ref _course, value); }
            get { return _course; }
        }

        public string PinButtonText { get { return Controller.GetResourceString(Controller.IsCoursePinned(Course) ? "Unpin" : "PinToStart"); } }

        public string PinButtonIcon { get { return Controller.IsCoursePinned(Course) ? "\uE196" : "\uE141"; } }

        public CourseViewModel()
        {
            GotoCourseContentCommand = new RelayCommand<CourseContent>(ExecuteGotoCourseContent);
            GotoUsersCommand = new RelayCommand(ExecuteGotoUsers);
            GotoEventsCommand = new RelayCommand(ExecuteGotoEvents);
            ModuleContentCommand = new RelayCommand<ModuleContent>(ExecuteModuleContent);
            GotoTeacherCommand = new RelayCommand<CourseUserWrapper>(ExecuteGotoTeacher);
            GotoNextAssignmentsCommand = new RelayCommand(ExecuteGotoNextAssignments);
            GotoCorrectedAssignmentsCommand = new RelayCommand(ExecuteGotoCorrectedAssignments);
            PinToStartCommand = new RelayCommand<FrameworkElement>(ExecutePinToStart);

            _courseModulesGroup.Title = "Modules";
            _courseModulesGroup.TopItems = _units;
            //_courseUsersGroup.Title = "Users";
            //_courseUsersGroup.TopItems = _users;

            //_groups = new object[] { _courseModulesGroup, _courseUsersGroup };
        }

        public async Task LoadContent(Course course)
        {
            Course = course;
            await Refresh();
        }

        public async Task LoadContent(long id)
        {
            if (!await Controller.LoginAsync())
                throw new InvalidOperationException("Login failed"); // TODO: redirect to login
            
            var courses = (await Api.GetEnrolledCoursesAsync(CurrentUser)).Data;
            await LoadContent(courses.First());
        }

        public async override Task Refresh()
        {
            await base.Refresh();
            Units.Clear();
            Teachers.Clear();

            IsLoading = true;
            var content = (await Api.GetCourseContentsAsync(Course.Id)).Data;
            var enrolledUsers = (await Api.GetCourseEnrolledUsersAsync(Course.Id)).Data;
            IsLoading = false;

            Units.AddMany(content.Select(a => new CourseContentWrapper(a)));
            Teachers.AddMany(enrolledUsers
                .Where(user => user.Roles.Any(role => role.Shortname.ToLower().Contains(UserRole.Teacher)))
                .Select(user => new CourseUserWrapper(user)));
        }

        private void ExecuteGotoCourseContent(CourseContent courseContent)
        {
            Controller.GotoCourseContent(courseContent);
        }

        private void ExecuteGotoUsers()
        {
            Controller.GotoCourseUsers(Course);
        }

        private void ExecuteGotoEvents()
        {
            Controller.GotoCourseEvents(Course);
        }

        private void ExecuteGotoTeacher(CourseUserWrapper userWrapper)
        {
            Controller.GotoTeacher(userWrapper.User);
        }

        private async void ExecuteModuleContent(ModuleContent moduleContent)
        {
            var result = await Controller.OpenModuleContentAsync(moduleContent);
            if (!result)
                await Controller.ShowMessageDialogAsync("Cannot download file from Moodle.");
        }

        private void ExecuteGotoNextAssignments()
        {
            Controller.GotoNextAssignments(Course);
        }

        private void ExecuteGotoCorrectedAssignments()
        {
            Controller.GotoCorrectedAssignments(Course);
        }

        private async void ExecutePinToStart(FrameworkElement element)
        {
            if (Controller.IsCoursePinned(Course))
            {
                await Controller.UnpinCourseAsync(Course, GetElementRect(element));
            }
            else
            {
                await Controller.PinCourseAsync(Course, GetElementRect(element));
            }
            RaisePropertyChanged("PinButtonIcon");
            RaisePropertyChanged("PinButtonText");
        }

        private Rect GetElementRect(FrameworkElement element)
        {
            var buttonTransform = element.TransformToVisual(null);
            var point = buttonTransform.TransformPoint(new Point());
            var rect = new Rect(point, new Size(element.ActualWidth, element.ActualHeight));
            return rect;
        }
    }
}
